/*
 * console2.cpp
 *
 *  Created on: Dec 14, 2013
 *      Author: killerg
 */

#include "console2.h"
#include "util.h"

#include <event2/buffer.h>

#include <unistd.h>

#include <fcntl.h>
#include <sys/types.h>
#include "net_s.h"


bool console_t2::init_log(const char* name) {
    std::string file_path;

    char buff[100];
    time_t now = time(NULL);
    strftime(buff,100,"%Y%m%d_%H%M%S",localtime(&now));
    file_path = fmt_cstr("%s/log/%s_%s_%d", get_deploy(), name, buff, getpid());

    fd = open(file_path.c_str(), O_CREAT | O_WRONLY, S_IRUSR | S_IWUSR);
    if (fd < 0)
        return false;

    _need_send = false;
//    _has_tran = false;
    _tran = NULL;

    _mask_f = E|W|I;
    _mask_s = E|W|I|C;

    return true;
}
bool console_t2::init_net() {
    if (!_processer.init()) {
        return false;
    }

    return net.init(2);
}
void console_t2::destroy() {
    while (NULL != _tran/* && _has_tran*/) {
        _tran->disconnect();
        net.update();
    }

    net.stop_accept();
    net.destroy();

    if (fd >= 0) {
        close(fd);
        fd = -1;
    }

    _processer.destroy();
}
void console_t2::update() {
    net.update();

    if (NULL == _tran)
        return;


    size_t len = 0;
    char* line = evbuffer_readln(_tran->input, &len, EVBUFFER_EOL_ANY);
    if (NULL != line) {
        std::string str = _processer.proc_gmcmd(line, this);
        evbuffer_add_printf(_tran->output, "%s\r\n", str.c_str());
        free(line);
        _need_send = true;
    }

    if (_need_send) {
        _need_send = false;
        _tran->deal_epoll(EPOLL_CTL_MOD, EPOLLIN|EPOLLOUT|EPOLLET);
    }
}

bool console_t2::start_accept(const char* ip, int port) {
    bool ok = net.start_accept(ip, port,
                [this](tran_s* tran){
                    if (NULL != _tran)
                        _tran->disconnect(false);
                    _tran = tran;
                },
                [this](tran_s* tran){
                    if (tran == _tran)
                        _tran = NULL;
                }
            );
    if (!ok) {
        UTIL_LOG(E, "console_t2::start_accept net start_accept failed");
    }
    return ok;
}
int console_t2::log(int mask, const char* fmt, ...) {
    va_list args;

    va_start(args, fmt);
    int n = vlog(mask, fmt, args);
    va_end(args);

    return n;
}
int console_t2::vlog(int mask, const char* fmt, va_list args) {
    char buffer[1024 * 1024];
    int len = 0;

    len = vsprintf(buffer, fmt, args);
    if (len <= 0)
        return 0;

    if (NULL != _tran && (_mask_s & mask)) {
        evbuffer_add(_tran->output, buffer, len);
        _need_send = true;
    }

    if (fd >= 0 && (_mask_f & mask)) {
        int wr = 0;
        while (wr < len) {
            int ret = write(fd, buffer+wr, len);
            if (ret > 0)
                wr += ret;
        }
    }

    return len;
}
bool console_t2::reg(const char* cmd, const char* args, handle_t handler) {
    return _processer._register_cmd(cmd, args, handler);
}
#include <array>
#include <iomanip>
#include <math.h>

void console_t2::update_watcher() {
    watch_ss.setf(std::_S_left);
    watch_ss.str("");
    int i=0;
    for (const auto &itr : nwatchers) {
        watch_ss.width(3);
        watch_ss << i++ ;
        watch_ss.width(20);
        watch_ss << std::get<0>(itr);
        watch_ss.width(10);
        auto value = std::get<1>(itr)();
        auto max = std::get<2>(itr)();
        watch_ss << value;
        if (max >= 0) {
            watch_ss << "|" << max;
        }
        watch_ss << std::endl;
    }
    for (const auto &itr : fwatchers) {
        watch_ss.width(3);
        watch_ss << i++ ;
        watch_ss.width(20);
        watch_ss << std::get<0>(itr);
        watch_ss.width(10);
        auto value = std::get<1>(itr)();
        auto max = std::get<2>(itr)();
        value = int(5 + value * 1000000) / 1000000.0f;
        watch_ss << value;
        if (max >= 0) {
        	const static int STARNUM = 10;
            double pct = (double)value / max;
            watch_ss << "|";
            int num = ceil(pct * STARNUM);
            for (int i=0; i<STARNUM; ++i) {
                if (i < num)
                    watch_ss << "*";
                else
                    watch_ss << " ";
            }
            watch_ss << "|";
        }
        watch_ss << std::endl;
    }
}
